<script setup>
import { computed, defineProps, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import * as echarts from 'echarts'
// import { line, lineRadial } from 'd3';

const props = defineProps({
    ids: Array
})
const routes = computed(() => 
    props.ids.map(id => allSourceLink.find(item => item.id === id)).filter(Boolean)
);
const activeIndex = ref(0);
const currentRoute = computed(() => routes.value[activeIndex.value] || { node: ['默认节点'], link:[] });
const allSourceLink = [
    { 
        id: 'sp-1', 
        node: ['业务应用层','数据库组件','存储子系统','磁盘阵列','磁盘驱动器、数据库表空间配置、数据库日志管理'], 
        link: ['业务处理延迟⬆️','查询响应时间⬆️','数据库磁盘IO延迟⬆️','磁盘空间使用率⬆️'],
    },
    {
        id: 'sp-2',
        node: ['业务应用层','数据库组件','查询优化器','锁管理器、事物管理器'],
        link: ['业务处理延迟⬆️','查询响应时间⬆️','锁等待时间⬆️']
    },
    {
        id: 'sp-3',
        node: ['业务应用层','数据库组件','Redis缓存、应用缓存、数据库缓存模块'],
        link: ['业务处理延迟⬆️','缓存命中率⬇️']
    },
    {
        id: 'sp-4',
        node: ['业务应用层','数据库组件','数据库连接池'],
        link: ['业务处理延迟⬆️','连接池耗尽⬆️']
    },
    {
        id: 'sp-5',
        node: ['业务应用层','数据库组件','事务管理器、数据库日志系统、锁管理器、SQL执行引擎'],
        link: ['业务处理延迟⬆️','事物回滚率⬆️']
    },
    {
        id: 'sp-6',
        node: ['业务应用层','缓存组件、消息队列组件'],
        link: ['业务处理延迟⬆️']
    },
    {
        id: 'sp-7',
        node: ['业务应用层','Web服务组件','CPU核心','用户态线程'],
        link: ['业务处理延迟⬆️','CPU使用率⬆️','用户态占用CPU⬆️']
    },
    {
        id: 'sp-8',
        node: ['业务应用层','Web服务组件','CPU核心','内核态线程'],
        link: ['业务处理延迟⬆️','CPU使用率⬆️','内核态占用CPU⬆️']
    },
    {
        id: 'sp-9',
        node: ['业务应用层','Web服务组件','CPU核心','中断控制器'],
        link: ['业务处理延迟⬆️','CPU使用率⬆️','中断率⬆️']
    },
    {
        id: 'sp-10',
        node: ['业务应用层','Web服务组件','内存模块','应用服务、堆内存、守护进程'],
        link: ['业务处理延迟⬆️','内存占用率⬆️','内存泄漏⬆️']
    },
    {
        id: 'sp-11',
        node: ['业务应用层','Web服务组件','内存模块','内存管理、交换空间'],
        link: ['业务处理延迟⬆️','内存占用率⬆️','Swap使用率⬆️']
    },
    {
        id: 'sp-12',
        node: ['业务应用层','Web服务组件','内存模块','页面管理、页管理子系统'],
        link: ['业务处理延迟⬆️','内存占用率⬆️','PageFault频率⬆️']
    },
    {
        id: 'sp-13',
        node: ['业务应用层','Web服务组件','磁盘子系统','IO调度器'],
        link: ['业务处理延迟⬆️','磁盘IO延迟⬆️','队列等待时间⬆️']
    },
    {
        id: 'sp-14',
        node: ['业务应用层','Web服务组件','磁盘子系统','RAID控制器、SSD/HSS'],
        link: ['业务处理延迟⬆️','磁盘IO延迟⬆️','IOPS⬇️']
    },
    {
        id: 'sp-15',
        node: ['业务应用层','Web服务组件','磁盘子系统','文件系统类型、磁盘硬件、挂载点配置'],
        link: ['业务处理延迟⬆️','磁盘IO延迟⬆️','磁盘利用率⬆️']
    },
    {
        id: 'sp-16',
        node: ['业务应用层','Web服务组件','操作系统整体调度器'],
        link: ['业务处理延迟⬆️','系统负载⬆️']
    },
    {
        id: 'sp-17',
        node: ['业务应用层','Web服务组件','进程管理器、异常应用程序'],
        link: ['业务处理延迟⬆️','僵尸进程数量⬆️']
    },
    {
        id: 'sp-18',
        node: ['业务应用层','网络组件','链路带宽、交换机2、网络接口'],
        link: ['业务处理延迟⬆️','带宽利用率⬆️']
    },
    {
        id: 'sp-19',
        node: ['业务应用层','网络组件','DNS服务器'],
        link: ['业务处理延迟⬆️','DNS解析失败⬆️']
    },
    {
        id: 'sp-20',
        node: ['业务应用层','网络组件','网络适配器','物理网卡、物理链路、QOS、交换机、路由器'],
        link: ['业务处理延迟⬆️','网络延迟⬆️','丢包率⬆️']
    },
    {
        id: 'sp-21',
        node: ['业务应用层','网络组件','网络适配器','网络拥塞、TCP协议栈、链路网'],
        link: ['业务处理延迟⬆️','网络延迟⬆️','TCP重传率⬆️']
    },
    {
        id: 'sp-22',
        node: ['业务应用层','内核模块加载器'],
        link: ['麒麟内核taint标志⬆️']
    },
    {
        id: 'sp-23',
        node: ['业务应用层','数据库组件','存储子系统、查询优化器'],
        link: ['业务处理延迟⬆️','查询响应时间⬆️']
    },
    {
        id: 'sp-24',
        node: ['业务应用层','数据库组件','磁盘阵列'],
        link: ['业务处理延迟⬆️','查询响应时间⬆️','数据库磁盘IO延迟⬆️']
    },
    {
        id: 'sp-25',
        node: ['业务应用层','Web服务组件','CPU核心'],
        line: ['业务处理延迟⬆️','CPU使用率⬆️']
    },
    {
        id: 'sp-26',
        node: ['业务应用层','Web服务组件','内存模块'],
        link: ['业务处理延迟⬆️','内存占用率⬇️']
    },
    {
        id: 'sp-27',
        node: ['业务应用层','Web服务组件',"磁盘子系统"],
        link: ['业务处理延迟⬆️','磁盘IO延迟⬆️']
    },
    {
        id: 'sp-28',
        node: ['业务应用层','网络组件','网络适配器'],
        link: ['业务处理延迟⬆️','网络延迟⬆️']
    }
]
// 1. 生成 ECharts 配置
function transformGraph(raw, startPos = [300, 300], step = 150) {
  if (!raw || !Array.isArray(raw.node) || !Array.isArray(raw.link)) {
    return { data: [], links: [] };
  }
  const [x0, y0] = startPos;
  const data = raw.node.map((name, i) => ({ name, x: x0 + i * 100, y: y0 + i * step, symbolSize: [i * 30 + 200, 50] }));
  const links = raw.link.map((label, i) => ({
    source: i,
    target: i + 1,
    label: { show: true, formatter: label,distance: -20 },
}));
  return { data, links };
}

// 2. 图表实例
const chartRefSource = ref(null);
let myChartSource = null;

// 3. 添加渲染函数 
const renderChart = () => {
    if (!chartRefSource.value || routes.value.length === 0) {
        return;
    }
    const { data, links } = transformGraph(currentRoute.value)
    const option = {
      animationDurationUpdate: 1500,
      animationEasingUpdate: 'quinticInOut',
      series: [
        {
          type: 'graph',
          layout: 'none',
          roam: true,
          symbol: 'roundRect',
          symbolSize: [150, 50],
          label: { show: true },
          edgeSymbol: ['none', 'arrow'],
          edgeSymbolSize: [4, 10],
          edgeLabel: {
            fontSize: 14,
            show: true,
            position: 'middle',
            rotate: 0
          },
          data,
          links,
          lineStyle: { opacity: 0.9, width: 2, curveness: 0 }
        }
      ]
    };
    if (!myChartSource) {
        myChartSource = echarts.init(chartRefSource.value);
    }
    myChartSource.setOption(option, true)
    myChartSource.resize()
}
// 4. 保证首次有数据时立即渲染
watch(
  routes,
  (list) => {
    activeIndex.value = Math.min(activeIndex.value, Math.max(0, list.length - 1));
    nextTick(renderChart)
  },
  { immediate: true }
);

// 5. 只要 currentRoute 变化就重绘
watch(
  currentRoute,
  () => {
    nextTick(renderChart)
  },
);

// 4. 生命周期
onMounted(() => {
  nextTick(() => {
    if(routes.value.length > 0) {
        renderChart();
    }
  });
  window,addEventListener('resize', () => myChartSource?.resize())
});

onBeforeUnmount(() => {
  myChartSource?.dispose();
});
</script>
<template>
<div class="sourceChart-content">
    <div class="sourceChart-body" ref="chartRefSource">

    </div>
    <div class="btn-group">
        <button
            v-for="(route, idx) in routes"
            :key="route.id"
            @click="activeIndex = idx"
            :class="{ active: activeIndex === idx }"
        >
            {{ route.node.at(-1) }}
        </button>
    </div>
</div>
</template>
<style>
div {
    width: 100%;
}
.sourceChart-body {
    height: 650px;
    width: 770px;
}
.btn-group {
  margin-bottom: 8px;
  display: flex;
  gap: 8px;
}
.btn-group button {
  padding: 6px 12px;
  border: 1px solid #ccc;
  background: #fff;
  cursor: pointer;
  border-radius: 10px;
}
.btn-group button.active {
  background: #409eff;
  color: #fff;
}
</style>